package com.info3k.client.commands.event;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.maps.client.MapType;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.control.LargeMapControl3D;
import com.google.gwt.maps.client.control.MapTypeControl;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.info3k.client.Info3K;
import com.info3k.client.components.InfoWindow;
import com.info3k.client.components.Rating;
import com.info3k.client.domain.Address;
import com.info3k.client.domain.Event;
import com.info3k.client.domain.Location;
import com.info3k.client.domain.User;

public class ShowEventCommand implements Command {
	
	private Info3K info3k;
	
	private RootPanel parent;
	
	private MapWidget map = new MapWidget();
	
	private Event event;
	
	private List<Address> associatedAddresses = new ArrayList<Address>();
	
	private Rating rating = new Rating(0, 10, Rating.LTR);
	
	private Button editButton = new Button(Info3K.msgs.editEvent());
	
	public ShowEventCommand(RootPanel p, Info3K info, Event ev){
		this.info3k = info;
		this.parent = p;
		this.event = ev;
	}
	
	public void execute() {
		parent.clear();
	
		map.setSize("280px", "280px");
		map.addControl(new LargeMapControl3D());
		map.setCurrentMapType(MapType.getSatelliteMap());
		map.addControl(new MapTypeControl());
		
		final VerticalPanel verPanel = new VerticalPanel();
		
		verPanel.setWidth("100%");
		parent.add(verPanel);
		
		HorizontalPanel hPanel1 = new HorizontalPanel();
		hPanel1.setWidth("100%");
		verPanel.add(hPanel1);
		
		hPanel1.add(new HTML("<h1>" + event.getTitle() + "</h1>"));
		User uu = info3k.getLoginManager().getUser();
		if(uu!=null){
			if(uu.getUsername().equals(event.getUser().getUsername())){
				hPanel1.add(editButton);
			}
		}
		verPanel.add(new HTML("<div class=\"h_line\"></div>"));
		
		hPanel1.setCellHorizontalAlignment(editButton, HorizontalPanel.ALIGN_RIGHT);
		
		editButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent e) {
				EditEventCommand cmd = new EditEventCommand(info3k, event);
				cmd.execute();
			}
		});
		
		final HorizontalPanel horPanel = new HorizontalPanel();
		verPanel.add(new HTML(event.getDescription() + "<hr>"));
		verPanel.add(horPanel);
		
		final VerticalPanel infoEventContent = new VerticalPanel();
		
		horPanel.add(infoEventContent);
		horPanel.add(map);
		
		horPanel.setCellWidth(infoEventContent, "100%");
		horPanel.setCellWidth(map, "280px");
		
		String s = Info3K.msgs.creator() + ": ";
		if(event.getUser()!=null) s += "<b>" + event.getUser().getUsername() + "</b>";
		infoEventContent.add(new HTML(s));
				
		if(event.getEventTime()!=null){
			String s4 = Info3K.msgs.eventDate() + ": ";
			s4 += "<b>" + DateTimeFormat.getMediumDateTimeFormat().format(event.getEventTime()) + "</b>";
			infoEventContent.add(new HTML(s4 + "<br><br>"));
		}
		
		for (Location loc : event.getLocations()) {
			for (Address address : loc.getAddresses()) {
				associatedAddresses.add(address);
			}
		}
				
		final Button showLocations = new Button(Info3K.msgs.associatedLocations() + " ["+ event.getLocations().length + "]");
		final Button showAddresses = new Button(Info3K.msgs.associatedAddresses() + " ["+ associatedAddresses.size() + "]");
		
		showLocations.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent e) {
				renderLocations(event.getLocations());
			}
		});
		
		showAddresses.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent e) {
				renderAddresses(associatedAddresses);
			}
		});
		
		showLocations.setWidth("160px");
		showAddresses.setWidth("160px");
		
		HorizontalPanel hPanel = new HorizontalPanel();
		
		infoEventContent.add(hPanel);
		
		if(event.getLocations().length>0){
			hPanel.add(showLocations);
			hPanel.setCellWidth(showLocations, "170px");
		}
		
		if(associatedAddresses.size()>0){
			hPanel.add(showAddresses);
			hPanel.setCellWidth(showAddresses, "170px");
		}
		
		String s1 = "<hr>" + Info3K.msgs.creationDate() + ": ";
		s1 += "<b>" + DateTimeFormat.getMediumDateTimeFormat().format(event.getCreationTime()) + "</b>";
		infoEventContent.add(new HTML(s1));
		
		String s2 = Info3K.msgs.views() + ": ";
		s2 += "<b>" + event.getViews() + "</b>";
		
		final HTML htmlView = new HTML(s2);
		infoEventContent.add(htmlView);
		
		String s3 = Info3K.msgs.rate() + ": ";
		String rate = event.getRate().toString();
		if(rate.length()>4) rate = rate.substring(0, 4);
		s3 += "<b>" + rate + "</b>";
		HorizontalPanel ratingPanel = new HorizontalPanel();
		
		final HTML html = new HTML(s3);
		ratingPanel.add(html);
		ratingPanel.add(rating);
		
		rating.setValue(event.getRate().intValue());
		
		ratingPanel.setCellWidth(html, "90px");
		
		infoEventContent.add(ratingPanel);
		
		renderLocations(event.getLocations());
		
		rating.addValueChangeHandler(new ValueChangeHandler<Integer>(){
			public void onValueChange(ValueChangeEvent<Integer> e) {
				Info3K.loader.setVisible(true);
				Info3K.infoService.rateEvent(event, Double.valueOf(e.getValue()), new AsyncCallback<Void>(){
					public void onFailure(Throwable caught) {
						Info3K.loader.setVisible(false);
						InfoWindow.showMessage(Info3K.msgs.error(), caught.getMessage());
					}

					public void onSuccess(Void result) {
						Info3K.loader.setVisible(false);
						InfoWindow.showMessage(Info3K.msgs.ok(), Info3K.msgs.eventRatedSuccessfully());
						Double newRate = ((event.getNumRates() * event.getRate()) + rating.getValue()) / (event.getNumRates()+1);
						event.setNumRates(event.getNumRates() + 1);
						event.setRate(newRate);
						rating.setReadOnly(true);
						String s3 = Info3K.msgs.rate() + ": ";
						String rate = event.getRate().toString();
						if(rate.length()>4) rate = rate.substring(0, 4);
						s3 += "<b>" + rate + "</b>";
						html.setHTML(s3);
					}
				});
			}
		});
		
		Info3K.infoService.viewEvent(event, new AsyncCallback<Void>(){
			public void onFailure(Throwable caught) {
				InfoWindow.showMessage(Info3K.msgs.error(), caught.getMessage());
			}

			public void onSuccess(Void result) {
				event.setViews(event.getViews() + 1);
				String s2 = Info3K.msgs.views() + ": ";
				s2 += "<b>" + event.getViews() + "</b>";
				
				htmlView.setHTML(s2);
			}
		});
	}
	
	private void renderLocations(Location[] locations){
		map.clearOverlays();
		for (Location location : locations) {
			for (String string : location.getLatLong()) {
				String[] array = string.split("%");
				if(array.length==2){
					MarkerOptions options = MarkerOptions.newInstance();
					String s = location.getLocationName();
					options.setTitle(s);
					Marker marker = new Marker(LatLng.newInstance(Double.parseDouble(array[0]),Double.parseDouble(array[1])), options);
					map.addOverlay(marker);
					map.setCenter(LatLng.newInstance(marker.getLatLng().getLatitude(), marker.getLatLng().getLongitude()), 14);
				}
			}
		}
	}
	
	private void renderAddresses(List<Address> addresses){
		map.clearOverlays();
		for (Address address : addresses) {
			MarkerOptions options = MarkerOptions.newInstance();
			String s = address.getAddress();
			if(address.getHouseNumber()!=null)  
				s += " " + address.getHouseNumber();
			options.setTitle(s);
			Marker marker = new Marker(LatLng.newInstance(address.getLat(),address.getLon()), options);
			map.addOverlay(marker);			
			map.setCenter(LatLng.newInstance(address.getLat(),address.getLon()), 14);
		}
	}
}
